package com.hcx.xml.sax;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

/**
 * 提供 SAX 内容处理是的路径定位和内容读取功能
 * @author 韩朝祥
 *
 */
public abstract class AbstractContentHandler implements ContentHandler {
	private static final String PATH_SEPARATOR = "/";
	private static final int CONTENT_CACHE_INIT_SIZE = 255;
	
	private boolean holdContent = false;
	private StringBuffer contentCache = new StringBuffer(CONTENT_CACHE_INIT_SIZE);
	private String currentPath = "";

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if(holdContent){
			contentCache.append(new String(ch, start, length));
		}
	}

	@Override
	public void endDocument() throws SAXException {
	}

	@Override
	public final void endElement(String uri, String localName, String qName)
			throws SAXException {
		internalHandleEndElement(uri, localName, qName);
		currentPath = currentPath.substring(0 , currentPath.lastIndexOf(PATH_SEPARATOR));
	}

	@Override
	public void endPrefixMapping(String prefix) throws SAXException {
	}

	@Override
	public void ignorableWhitespace(char[] ch, int start, int length)
			throws SAXException {
	}

	@Override
	public void processingInstruction(String target, String data)
			throws SAXException {
	}

	@Override
	public void setDocumentLocator(Locator locator) {
	}

	@Override
	public void skippedEntity(String name) throws SAXException {
		
	}

	@Override
	public void startDocument() throws SAXException {
		
	}

	@Override
	public final void startElement(String uri, String localName, String qName,
			Attributes atts) throws SAXException {
		currentPath = currentPath + PATH_SEPARATOR + localName;
		internalHandleStartElement(uri, localName, qName, atts);
	}

	@Override
	public void startPrefixMapping(String prefix, String uri)
			throws SAXException {
	}
	
	protected final void startHoldContent() {
		this.holdContent = true;
	}
	
	protected final void stopHoldContent() {
		this.holdContent = false;
	}
	
	protected final void cleanContent() {
		contentCache = new StringBuffer(CONTENT_CACHE_INIT_SIZE);
	}
	
	protected final String getContent() {
		return contentCache.toString();
	}
	
	protected final boolean isHoldContent() {
		return holdContent;
	}
	
	protected final String getCurrentPath() {
		return currentPath;
	}

	/**
	 * 子类重写该方法实现元素处理
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param atts
	 */
	protected abstract void internalHandleStartElement(String uri, String localName, String qName,
			Attributes atts) throws SAXException;
	
	protected abstract void internalHandleEndElement(String uri, String localName, String qName)
			throws SAXException;
}
